package com.speedchina.common.rsa.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ：wangxiaodong
 * @description：TODO
 * @date ：2021/4/19 9:49
 */
public class RSAUtils {
    private static final String src = "abcdefghijklmnopqrstuvwxyz";

    public static void main(String[] args) throws Exception {
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAoKgtf/mSR7oaqufNiwz470qdqIMdHVRj7EMAaV8Q03cU73IMVbQHukjdCusg5fuGvX57zMH4Tc8MZSDKqKnHeAg8MqDgGKBlkhruZCYTTYRwa38o/HUvPg3qbQDbRmu3rWPHAjsd/Rst6yzv653zgGbO1ZlhC7QeRd5R7BqSAQIDAQAB";
        String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAICgqC1/+ZJHuhqq582LDPjvSp2ogx0dVGPsQwBpXxDTdxTvcgxVtAe6SN0K6yDl+4a9fnvMwfhNzwxlIMqoqcd4CDwyoOAYoGWSGu5kJhNNhHBrfyj8dS8+DeptANtGa7etY8cCOx39Gy3rLO/rnfOAZs7VmWELtB5F3lHsGpIBAgMBAAECgYAk63g6TyBYf2QIoYOVeNMJZM3bAPJZWgDOCZOVu6kA0GG+zZfDuJnLGgouACNLNxgCLcPvTu9iERtb6G8IHG9WnBuubP99stojkO5XUUyNJMRMFMqKKkxvzaZZ8iCobVOflAJg5mrtcUyKp7hKFvAYUmrojB85+oTBUbDQ9IZzEQJBAMcZ5XtofLXa2/rQF2JXeaQg+XHCSfm7MuwtYz8XcjuAKEsyDhh5iJm4NNuKHyKiFk8EiR6WIoKL8VbmaI+ymyUCQQClYvYKk66SOodip11OX5XK2OLCEXqv1tJjnwUAjuOQsk7eNtOy0ZpynYiGMuku29agWVhi1/5KdrA6Q/a76LKtAkAwWL96yhKObkjAjMtA3BDzo/Yug4lHFQf2hcb1yRG6FRKzv8Hge5KKEUr0jIOm+0kDgwxw2vAiVy0Rdv2o9yvpAkAR3JxCDC0gcd3JU9YJ7tzYqY/j8ctUTlkulTAPHV+Kcxd9fGJkv6p0knr6M2lnvCpz6vJWyokWNbdWs5xkMv+JAkA6/JtmZN6enkTD/wvGtPRWtLYAsIl4Ajbmq1J65OZToc3BD/zINk3jg3S75PCTN3Wp7Be7bLGHTC3hz7Dx0iYj";
        String str = "{\"username\": \"wxd\", \"password\": \"123456\"}";
        String text = encryptByPublicKey(publicKey,"admin");
        System.err.println(text);
        String text2 = encryptByPublicKey(publicKey,"123456");
        System.err.println(text2);
        System.err.println(decryptByPrivateKey(privateKey,text));
        String privateText = encryptByPrivateKey(privateKey,str);
        System.err.println(privateText);
        System.err.println(decryptByPublicKey(publicKey,privateText));

        System.out.println("\n");
        RSAKeyPair keyPair = generateKeyPair();
        System.out.println("公钥：" + keyPair.getPublicKey());
        System.out.println("私钥：" + keyPair.getPrivateKey());
        System.out.println("\n");
        test1(keyPair, src);
        System.out.println("\n");
        test2(keyPair, src);
        System.out.println("\n");
//        System.err.println(JSON.parseObject("{\"username\":\"wxd\",\"password\":\"123456\"}", User.class));
    }

    public static Map<String,String> generatePublicKeyPrivateKey() throws NoSuchAlgorithmException {
        Map<String,String> map = new HashMap<String,String>();
        RSAKeyPair keyPair = generateKeyPair();
        String publicKey = keyPair.getPublicKey();
        String privateKey = keyPair.getPrivateKey();
        map.put("publicKey",publicKey);
        map.put("privateKey",privateKey);
        return map;
    }
    /**
     * 获取公钥
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String generatePublicKey() throws NoSuchAlgorithmException {
        RSAKeyPair keyPair = generateKeyPair();
        return keyPair.getPublicKey();
    }

    /**
     * 获取私钥
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String generatePrivateKey() throws NoSuchAlgorithmException {
        RSAKeyPair keyPair = generateKeyPair();
        return keyPair.getPrivateKey();
    }
    /**
     * 公钥加密私钥解密
     */
    private static void test1(RSAKeyPair keyPair, String source) throws Exception {
        System.out.println("***************** 公钥加密私钥解密开始 *****************");
        String text1 = encryptByPublicKey(keyPair.getPublicKey(), source);
        String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
        System.out.println("加密前：" + source);
        System.out.println("加密后：" + text1);
        System.out.println("解密后：" + text2);
        if (source.equals(text2)) {
            System.out.println("解密字符串和原始字符串一致，解密成功");
        } else {
            System.out.println("解密字符串和原始字符串不一致，解密失败");
        }
        System.out.println("***************** 公钥加密私钥解密结束 *****************");
    }

    /**
     * 私钥加密公钥解密
     *
     * @throws Exception
     */
    private static void test2(RSAKeyPair keyPair, String source) throws Exception {
        System.out.println("***************** 私钥加密公钥解密开始 *****************");
        String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), source);
        String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
        System.out.println("加密前：" + source);
        System.out.println("加密后：" + text1);
        System.out.println("解密后：" + text2);
        if (source.equals(text2)) {
            System.out.println("解密字符串和原始字符串一致，解密成功");
        } else {
            System.out.println("解密字符串和原始字符串不一致，解密失败");
        }
        System.out.println("***************** 私钥加密公钥解密结束 *****************");
    }

    /**
     * 公钥解密
     *
     * @param publicKeyText
     * @param text
     * @return
     * @throws Exception
     */
    public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 私钥加密
     *
     * @param privateKeyText
     * @param text
     * @return
     * @throws Exception
     */
    public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    /**
     * 私钥解密
     *
     * @param privateKeyText
     * @param text
     * @return
     * @throws Exception
     */
    public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 公钥加密
     *
     * @param publicKeyText
     * @param text
     * @return
     */
    public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    /**
     * 构建RSA密钥对
     *
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static RSAKeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
        RSAKeyPair rsaKeyPair = new RSAKeyPair(publicKeyString, privateKeyString);
        return rsaKeyPair;
    }


    /**
     * RSA密钥对对象
     */
    public static class RSAKeyPair {

        private String publicKey;
        private String privateKey;

        public RSAKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey() {
            return publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

    }

}
